package com.example.spring_source_code.anno.component01;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

public class ComponentScanBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) {
        try {
            ComponentScan componentScan = Config.class.getAnnotation(ComponentScan.class);
            //获取包下的所有类
            CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
            AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
            for (String basePackage : componentScan.basePackages()) {
                //路径转化 Resource是读取class目录下的
                String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";

                PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
                Resource[] resource = resolver.getResources(path);
                //读取类上的所有元信息
                for (Resource resource1 : resource) {
                    MetadataReader metadataReader = readerFactory.getMetadataReader(resource1);
                    boolean hasAnnotation = metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName());
                    boolean hasMetaAnnotation = metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName());
                    String className = metadataReader.getClassMetadata().getClassName();
//                System.out.println(className + "contain Component:"+hasAnnotation);
//                System.out.println(className + "contain Component MetaData:" + hasMetaAnnotation);
                    //注入容器
                    if (hasAnnotation || hasMetaAnnotation) {
                        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(className).getBeanDefinition();
                        //生成Bean的名称
                        if (configurableListableBeanFactory instanceof DefaultListableBeanFactory) {
                            DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
                            String beanName = beanNameGenerator.generateBeanName(beanDefinition, defaultListableBeanFactory);
                            defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition);
                        }
                    }
                }

            }

        } catch (Exception e) {

        }

    }
}
